package com.zhang.bingmei_incomeexpenditure.service.service.Impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhang.bingmei_incomeexpenditure.config.CustomColumnWidthHandler;
import com.zhang.bingmei_incomeexpenditure.config.ForceNewRowMergeStrategy;
import com.zhang.bingmei_incomeexpenditure.entity.commom.DataScope;
import com.zhang.bingmei_incomeexpenditure.entity.ie.*;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleResult;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleSum;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleVO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.updateNew.UpdateDoubleDTO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.updateNew.UpdateDoubleVO;
import com.zhang.bingmei_incomeexpenditure.entity.Utils.IECommUtil;
import com.zhang.bingmei_incomeexpenditure.entity.Utils.IDWork;
import com.zhang.bingmei_incomeexpenditure.entity.Utils.SecurityPlusUtils;
import com.zhang.bingmei_incomeexpenditure.entity.build.IncomeExpenditureBuilder;
import com.zhang.bingmei_incomeexpenditure.entity.comCity.CommCity;
import com.zhang.bingmei_incomeexpenditure.entity.commom.BeanCopyUtil;
import com.zhang.bingmei_incomeexpenditure.mapper.CommCityMapper;
import com.zhang.bingmei_incomeexpenditure.mapper.IncomeExpenditureMapper;
import com.zhang.bingmei_incomeexpenditure.service.CommCityService;
import com.zhang.bingmei_incomeexpenditure.service.IncomeExpenditureService;
import com.zhang.bingmei_incomeexpenditure.service.chain.ValidationHandler;
import com.zhang.bingmei_incomeexpenditure.service.factory.ValidationChainFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.zhang.comm.constant.Constant.StartYear;
import static com.zhang.comm.constant.Constant.EndYear;

/**
 * @author zsj
 * @description 针对表【income_expenditure(病媒生物防制工作经费收支表)】的数据库操作Service实现
 * @createDate 2025-10-14 10:02:41
 */
@Service
@Slf4j
public class V2IncomeExpenditureServiceImpl extends ServiceImpl<IncomeExpenditureMapper, IncomeExpenditure>
        implements IncomeExpenditureService {

    @Resource
    private IncomeExpenditureMapper incomeExpenditureMapper;
    @Resource
    private CommCityService commCityService;
    @Resource
    private CommCityMapper commCityMapper;

    // ======================== 控制层直接调用的核心方法 ========================

    /**
     * 获取数据权限
     */
    @Override
    public DataScope getDataScopeByIE() {
        int minLevel = SecurityPlusUtils.getMinLevel();
        String area = SecurityPlusUtils.getArea();
        DataScope dataScope = new DataScope();
        dataScope.setUserId("1781989837734240256");
        dataScope.setMinLevel(minLevel);

        if (StringUtils.isNotBlank(area) && minLevel != -1) {
            String[] areaList = area.split(",");
            if (minLevel == 1 || minLevel == 2) {
                dataScope.setArea("460000");
            } else if (minLevel == 3 && areaList.length >= 2) {
                dataScope.setArea(areaList[0] + "," + areaList[1]);
            } else if (minLevel == 4 && areaList.length >= 3) {
                if (area.contains("460100") || area.contains("460200") || area.contains("460300")) {
                    dataScope.setArea(areaList[0] + "," + areaList[1] + "," + areaList[2]);
                }
            }
        }
        return dataScope;
    }

    /**
     * 获取所有区域（含年份）
     */
    @Override
    public List<CodeCityNameAndYearVO> getAllDistrict(IncomeExpenditurePageDTO dto) {
        try {
            DataScope dataScope = getAllDistrictPrefix();
            String prefix = dataScope.getArea();
            if (StringUtils.isEmpty(prefix)) {
                throw new RuntimeException("区域前缀为空");
            }

            List<String> districtAfter = getAllDistrictAfter(dataScope);
            int minLevel = SecurityPlusUtils.getMinLevel();
            if (minLevel == -1) {
                throw new RuntimeException("用户角色信息错误");
            }

            // 拼接完整区域编码
            List<String> districts = new ArrayList<>();
            for (String s : districtAfter) {
                if (StringUtils.isEmpty(s)) continue;
                if (minLevel == 1 || minLevel == 2) {
                    districts.add(prefix + "," + s);
                } else if (minLevel == 3 && (prefix.contains("460100") || prefix.contains("460200") || prefix.contains("460300"))) {
                    districts.add(prefix + "," + s);
                }
            }

            // 兜底逻辑
            if (districts.isEmpty() && StringUtils.isNotBlank(prefix) && (minLevel == 3 || minLevel == 4)) {
                districts.add(prefix);
            }

            if (districts.isEmpty()) {
                return Collections.emptyList();
            }

            // 查询城市信息
            List<CommCity> commCities = commCityMapper.selectList(new LambdaQueryWrapper<CommCity>()
                    .in(CommCity::getLevelCode, districts)
                    .eq(CommCity::getDeleted, 0)
                    .orderByAsc(CommCity::getCode));

            if (commCities.isEmpty()) {
                throw new RuntimeException("未查询到城市数据");
            }

            // 处理城市名称前缀
            commCities.forEach(city -> {
                String levelCode = city.getLevelCode();
                String name = city.getName();
                if (StringUtils.isNotBlank(levelCode) && StringUtils.isNotBlank(name)) {
                    if (levelCode.contains("460100") && !name.startsWith("海口市-")) {
                        city.setName("海口市-" + name);
                    } else if (levelCode.contains("460200") && !name.startsWith("三亚市-")) {
                        city.setName("三亚市-" + name);
                    } else if (levelCode.contains("460300") && !name.startsWith("三沙市-")) {
                        city.setName("三沙市-" + name);
                    }
                }
            });

            // 构建年份列表
            List<Integer> years = new ArrayList<>();
            Integer startYear = dto.getStartYear() == null ? StartYear : dto.getStartYear();
            Integer endYear = dto.getEndYear() == null ? EndYear : dto.getEndYear();
            for (int i = startYear; i <= endYear; i++) {
                years.add(i);
            }

            // 转换为返回VO
            return commCities.stream()
                    .map(city -> new CodeCityNameAndYearVO(city.getCode(), city.getName(), years))
                    .collect(Collectors.toList());
        } catch (RuntimeException e) {
            log.error("获取所有区域信息异常", e);
            throw new RuntimeException("获取所有区域信息异常：" + e.getMessage());
        }
    }

    /**
     * 查询收支数据（Double类型返回）
     */
    @Override
    public SelectDoubleResult getAllIEData(IncomeExpenditurePageDTO dto) {
        try {
            DataScope dataScope = getAllDistrictPrefix();
            String prefix = dataScope.getArea();
            if (StringUtils.isEmpty(prefix)) {
                throw new RuntimeException("区域前缀为空");
            }

            List<String> districtAfter = getAllDistrictAfter(dataScope);
            int minLevel = SecurityPlusUtils.getMinLevel();
            if (minLevel == -1) {
                throw new RuntimeException("用户角色信息错误");
            }

            // 拼接完整区域编码
            List<String> districts = new ArrayList<>();
            for (String s : districtAfter) {
                if (StringUtils.isEmpty(s)) continue;
                if (minLevel == 1 || minLevel == 2) {
                    districts.add(prefix + "," + s);
                } else if (minLevel == 3) {
                    if (prefix.contains("460100") || prefix.contains("460200") || prefix.contains("460300")) {
                        districts.add(prefix + "," + s);
                    } else {
                        districts.add(prefix);
                    }
                } else if (minLevel == 4 && !districts.contains(prefix)) {
                    districts.add(prefix);
                }
            }

            // 兜底逻辑
            if (districts.isEmpty() && StringUtils.isNotBlank(prefix) && (minLevel == 3 || minLevel == 4)) {
                districts.add(prefix);
            }

            if (districts.isEmpty()) {
                throw new RuntimeException("没有有效的区域编码");
            }

            // 构建查询条件
            LambdaQueryWrapper<IncomeExpenditure> queryWrapper = new LambdaQueryWrapper<IncomeExpenditure>()
                    .in(IncomeExpenditure::getLevelCode, districts)
                    .ge(IncomeExpenditure::getYear, dto.getStartYear() == null ? StartYear : dto.getStartYear())
                    .le(IncomeExpenditure::getYear, dto.getEndYear() == null ? EndYear : dto.getEndYear())
                    .eq(IncomeExpenditure::getDeleted, 0)
                    .orderByAsc(IncomeExpenditure::getCode)
                    .orderByAsc(IncomeExpenditure::getDistrict)
                    .orderByAsc(IncomeExpenditure::getYear);

            // 执行查询
            List<IncomeExpenditure> incomeExpenditures = incomeExpenditureMapper.selectList(queryWrapper);

            // 处理区域名称前缀
            incomeExpenditures.forEach(ie -> {
                String levelCode = ie.getLevelCode();
                String district = ie.getDistrict();
                if (StringUtils.isNotBlank(levelCode) && StringUtils.isNotBlank(district)) {
                    if (levelCode.contains("460100") && !district.startsWith("海口市-")) {
                        ie.setDistrict("海口市-" + district);
                    } else if (levelCode.contains("460200") && !district.startsWith("三亚市-")) {
                        ie.setDistrict("三亚市-" + district);
                    } else if (levelCode.contains("460300") && !district.startsWith("三沙市-")) {
                        ie.setDistrict("三沙市-" + district);
                    }
                }
            });

            // 转换为VO
            List<UpdateDoubleVO> voList = incomeExpenditures.stream()
                    .map(this::iEToVO)
                    .collect(Collectors.toList());
            List<SelectDoubleVO> doubleVOS = BeanCopyUtil.copyListToList(voList, SelectDoubleVO.class);

            // 计算合计
            SelectDoubleSum sum = calculateDoubleTotalSum(incomeExpenditures);

            // 封装结果
            SelectDoubleResult result = new SelectDoubleResult();
            result.setSelectDoubleResults(doubleVOS);
            result.setSelectDoubleSum(sum);
            return result;
        } catch (RuntimeException e) {
            log.error("获取收支数据异常", e);
            throw new RuntimeException("获取收支数据异常：" + e.getMessage());
        }
    }

    /**
     * 批量新增/修改收支数据（Double转Long存储）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<UpdateDoubleVO> batchUpdateIncomeExpenditureDataLong2(List<UpdateDoubleDTO> updateList) {
        // 1. 基础校验
        if (updateList.isEmpty()) {
            throw new RuntimeException("待处理数据列表不能为空");
        }

        // 2. 权限校验
        if (!IECommUtil.isUpdateButton()) {
            throw new RuntimeException("当前用户无修改收支数据的权限");
        }

        // 3. 构建校验链并执行校验
        ValidationHandler validationChain = ValidationChainFactory.buildUpdateValidationChain(incomeExpenditureMapper);
        updateList.forEach(validationChain::validate);

        // 4. 分组：修改/新增
        Map<Boolean, List<UpdateDoubleDTO>> groupedData = updateList.stream()
                .collect(Collectors.partitioningBy(dto -> StringUtils.isNotBlank(dto.getId())));
        List<UpdateDoubleDTO> updateDTOList = groupedData.get(Boolean.TRUE);
        List<UpdateDoubleDTO> insertDTOList = groupedData.get(Boolean.FALSE);

        // 5. 处理修改和新增逻辑
        List<IncomeExpenditure> updateEntities = handleUpdateData(updateDTOList);
        List<IncomeExpenditure> insertEntities = handleInsertData(insertDTOList);

        // 6. 批量操作
        if (!updateEntities.isEmpty()) {
            this.updateBatchById(updateEntities);
        }
        if (!insertEntities.isEmpty()) {
            this.saveBatch(insertEntities);
        }

        // 7. 构建并返回结果
        return buildResult(updateEntities, insertEntities);
    }

    /**
     * 导出收支数据
     */
    @Override
    public void exportIncomeExpenditure(IncomeExpenditurePageDTO dto, HttpServletResponse response) throws Exception {
        //获取数据
        SelectDoubleResult oldData = getAllIEData(dto);
        //数据封装
        SelectDoubleResult exportResultData = new SelectDoubleResult();
        List<SelectDoubleVO> list = BeanCopyUtil.copyListToList(oldData.getSelectDoubleResults(), SelectDoubleVO.class);
        exportResultData.setSelectDoubleResults(list);
        exportResultData.setSelectDoubleSum(oldData.getSelectDoubleSum());

        String fileName = "file/fillexcel/IE-template2.xlsx";
        // 从classpath根目录读取模板文件（编译后resources目录下的文件会在根目录）
        InputStream templateStream = getClass().getClassLoader().getResourceAsStream(fileName);

        if (templateStream == null) {
            log.error("收支情况导出模板文件不存在: {}，请确保文件位于 vector-module/vector-admin/src/main/resources/ 目录下", fileName);
            throw new RuntimeException("收支情况导出模板文件不存在: " + fileName);
        }

        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=example.xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        // ---------- 1. 准备 Map（非列表部分） ----------
        Map<String, Object> dataMap = new HashMap<>();

        IncomeExpenditurePageDTO formatDto = IECommUtil.getDTO(dto);
        dataMap.put("startDate", formatDto.getStartDateStr());
        dataMap.put("endDate", formatDto.getEndDateStr());
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> sumMap = mapper.convertValue(exportResultData.getSelectDoubleSum(), Map.class);

        dataMap.putAll(sumMap);
        // ---------- 2. 准备 List（列表部分） ----------
        List<SelectDoubleVO> detailList = exportResultData.getSelectDoubleResults();
        // ---------- 3. 写出 ----------

        Map<Integer, Integer> columnWidthMap = new HashMap<>();
        columnWidthMap.put(0, 22);  // 0: 市辖区
        columnWidthMap.put(1, 10);  // 1: 年度
        columnWidthMap.put(2, 16);  // 2: 市级下拨经费
        columnWidthMap.put(3, 16);  // 3: 区级配套经费
        columnWidthMap.put(4, 22);  // 4: 其他（财政专项、单位自筹等）
        columnWidthMap.put(5, 16);  // 5: 经费来源合计
        columnWidthMap.put(6, 28);  // 6: 购置、维修、维护“防蚊、防蚊蝇”设施支出
        columnWidthMap.put(7, 22);  // 7: 购买消杀设备、药品支出
        columnWidthMap.put(8, 26);  // 8: 病媒生物防制相关宣传费、印刷费
        columnWidthMap.put(9, 30);  // 9: 组织专家开展区内病媒防制工作研讨等支出
        columnWidthMap.put(10, 24); // 10: 购买第三方病媒防制服务支出
        columnWidthMap.put(11, 22); // 11: 其他不属于上述用途的支出
        columnWidthMap.put(12, 18); // 12: 已实际完成支付合计
        columnWidthMap.put(13, 18); // 13: 被收回的市级下拨经费
        columnWidthMap.put(14, 18); // 14: 被收回的区级配套经费

        CustomColumnWidthHandler columnWidthHandler = new CustomColumnWidthHandler(columnWidthMap); // 自定义列宽处理器

        //创建自定义合并规则（这里注意版本问题！！！被坑了）
        ForceNewRowMergeStrategy mergeStrategy = new ForceNewRowMergeStrategy(0, new int[]{0});

        ExcelWriter excelWriter = EasyExcel.write(outputStream)
                .withTemplate(templateStream)
                .excelType(ExcelTypeEnum.XLSX)
                .build();
        //这一行必须加：否则会遇见占位符覆盖的现象，这个比较恶心，会导致最后一行合计无法正常显示
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        WriteSheet writeSheet = EasyExcel.writerSheet()
                //应用合并规则
                .registerWriteHandler(mergeStrategy)
                .registerWriteHandler(columnWidthHandler) // 注册列宽处理器
                .build();
        // 关键：分两次 fill
        // 合计、日期等普通占位符
        excelWriter.fill(dataMap, writeSheet);
        // 列表占位符  如果是多个的话，就会用到这个FillWrapper，我这是为了做演示，就给你加了一下，对应的模板也对应加了一下
        excelWriter.fill(new FillWrapper("data", detailList), fillConfig, writeSheet);
        excelWriter.finish();
    }

    /**
     * 获取收支数据（Long类型返回）
     */
    @Override
    public IncomeExpenditureResult getIncomeExpenditureData(IncomeExpenditurePageDTO dto) {
        DataScope scope = this.getDataScopeByIE();
        Integer roleLevel = SecurityPlusUtils.getMinLevel();
        List<String> citys = this.listByDataScopeArea(scope, roleLevel);
        return this.getCityNamesByArea(scope.getArea(), citys, dto);
    }

    /**
     * 获取收支数据（Double类型返回，按区域过滤）
     */
    @Override
    public SelectDoubleResult getIncomeExpenditureDoubleData(IncomeExpenditurePageDTO dto) {
        DataScope scope = this.getDataScopeByIE();
        Integer roleLevel = SecurityPlusUtils.getMinLevel();
        List<String> citys = this.listByDataScopeArea(scope, roleLevel);
        return this.getCityNamesByAreaToDouble(scope.getArea(), citys, dto);
    }

    @Override
    public List<UpdateDoubleVO> batchUpdateIncomeExpenditureDataLong(List<UpdateDoubleDTO> updateList) {
        return Collections.emptyList();
    }

    /**
     * 按区域查询收支数据（Long类型）
     */
    @Override
    public IncomeExpenditureResult getCityNamesByArea(String userRoleCity, List<String> areas, IncomeExpenditurePageDTO dto) {
        if (areas == null || areas.isEmpty()) {
            IncomeExpenditureResult emptyResult = new IncomeExpenditureResult();
            emptyResult.setIncomeExpenditureDetailVOList(Collections.emptyList());
            emptyResult.setIncomeExpenditureTotalSum(new IncomeExpenditureTotalSum());
            return emptyResult;
        }

        // 拼接区域编码
        List<String> levelCodeList = areas.stream()
                .map(city -> userRoleCity + "," + city)
                .collect(Collectors.toList());

        // 查询数据
        LambdaQueryWrapper<IncomeExpenditure> queryWrapper = new LambdaQueryWrapper<IncomeExpenditure>()
                .in(IncomeExpenditure::getLevelCode, levelCodeList)
                .ge(IncomeExpenditure::getYear, dto.getStartYear() == null ? StartYear : dto.getStartYear())
                .le(IncomeExpenditure::getYear, dto.getEndYear() == null ? EndYear : dto.getEndYear())
                .eq(IncomeExpenditure::getDeleted, 0)
                .orderByAsc(IncomeExpenditure::getCode)
                .orderByAsc(IncomeExpenditure::getDistrict)
                .orderByAsc(IncomeExpenditure::getYear);

        List<IncomeExpenditure> incomeExpenditures = incomeExpenditureMapper.selectList(queryWrapper);

        // 转换为VO
        List<IncomeExpenditureDetailVO> detailVOS = incomeExpenditures.stream()
                .map(entity -> BeanCopyUtil.copy(entity, IncomeExpenditureDetailVO.class))
                .collect(Collectors.toList());

        // 计算合计
        IncomeExpenditureTotalSum sum = new IncomeExpenditureTotalSum();
        sum.setCityAllocatedSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getCityAllocated));
        sum.setDistrictAllocatedSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getDistrictAllocated));
        sum.setOtherFundsSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getOtherFunds));
        sum.setTotalFundsSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getTotalFunds));
        sum.setPurchaseMaintainSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getPurchaseMaintain));
        sum.setPurchaseEquipmentSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getPurchaseEquipment));
        sum.setDiseasePreventionSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getDiseasePrevention));
        sum.setExpertTrainingSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getExpertTraining));
        sum.setThirdPartyServiceSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getThirdPartyService));
        sum.setOtherPaymentSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getOtherPayment));
        sum.setTotalPaymentSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getTotalPayment));
        sum.setCityRecoveredSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getCityRecovered));
        sum.setDistrictRecoveredSum(sumByFunction(incomeExpenditures, IncomeExpenditure::getDistrictRecovered));

        // 封装结果
        IncomeExpenditureResult result = new IncomeExpenditureResult();
        result.setIncomeExpenditureDetailVOList(detailVOS);
        result.setIncomeExpenditureTotalSum(sum);
        return result;
    }

    /**
     * 按区域查询收支数据（Double类型）
     */
    @Override
    public SelectDoubleResult getCityNamesByAreaToDouble(String userRoleCity, List<String> areas, IncomeExpenditurePageDTO dto) {
        if (areas == null || areas.isEmpty()) {
            SelectDoubleResult emptyResult = new SelectDoubleResult();
            emptyResult.setSelectDoubleResults(Collections.emptyList());
            emptyResult.setSelectDoubleSum(new SelectDoubleSum());
            return emptyResult;
        }

        // 拼接区域编码
        List<String> levelCodeList = areas.stream()
                .map(city -> userRoleCity + "," + city)
                .collect(Collectors.toList());

        // 查询数据
        LambdaQueryWrapper<IncomeExpenditure> queryWrapper = new LambdaQueryWrapper<IncomeExpenditure>()
                .in(IncomeExpenditure::getLevelCode, levelCodeList)
                .ge(IncomeExpenditure::getYear, dto.getStartYear() == null ? StartYear : dto.getStartYear())
                .le(IncomeExpenditure::getYear, dto.getEndYear() == null ? EndYear : dto.getEndYear())
                .eq(IncomeExpenditure::getDeleted, 0)
                .orderByAsc(IncomeExpenditure::getCode)
                .orderByAsc(IncomeExpenditure::getDistrict)
                .orderByAsc(IncomeExpenditure::getYear);

        List<IncomeExpenditure> incomeExpenditures = incomeExpenditureMapper.selectList(queryWrapper);

        // 转换为VO
        List<UpdateDoubleVO> voList = incomeExpenditures.stream()
                .map(this::iEToVO)
                .collect(Collectors.toList());
        List<SelectDoubleVO> doubleVOS = BeanCopyUtil.copyListToList(voList, SelectDoubleVO.class);

        // 计算合计
        SelectDoubleSum sum = calculateDoubleTotalSum(incomeExpenditures);

        // 封装结果
        SelectDoubleResult result = new SelectDoubleResult();
        result.setSelectDoubleResults(doubleVOS);
        result.setSelectDoubleSum(sum);
        return result;
    }

    /**
     * 获取区域列表（编码+名称）
     */
    @Override
    public List<CodeNameVO> getDistricts() {
        DataScope scope = this.getDataScopeByIE();
        String area = scope.getArea();
        Integer roleLevel = SecurityPlusUtils.getMinLevel();
        List<String> oldDistrictCodes = this.listByDataScopeArea(scope, roleLevel);

        // 拼接完整编码
        List<String> districtCodes = oldDistrictCodes.stream()
                .map(code -> area + "," + code)
                .collect(Collectors.toList());

        return commCityMapper.selectCodeAndNameByCodes(districtCodes);
    }

    /**
     * 按数据权限获取区域列表
     */
    @Override
    public List<String> listByDataScopeArea(DataScope dataScope, Integer role) {
        if (role == null || role == -1) {
            throw new RuntimeException("用户角色信息错误");
        }

        if (dataScope == null || StringUtils.isEmpty(dataScope.getArea())) {
            return Collections.emptyList();
        }

        // 查询区域信息
        List<CommCity> cityList = commCityMapper.selectDistinctLevelCodeByArea(dataScope.getArea());
        if (cityList.isEmpty()) {
            return Collections.emptyList();
        }

        // 处理区域编码
        Set<String> codeSet = new HashSet<>();
        for (CommCity city : cityList) {
            String[] codesList = city.getLevelCode().split(",");
            if (role == 1 || role == 2) {
                if (codesList.length >= 2) {
                    if ((codesList[1].equals("460100") || codesList[1].equals("460200") || codesList[1].equals("460300")) && codesList.length >= 3) {
                        codeSet.add(codesList[1] + "," + codesList[2]);
                    } else if (codesList.length == 2) {
                        codeSet.add(codesList[1]);
                    }
                }
            } else if (role == 3 && codesList.length >= 3) {
                codeSet.add(codesList[2]);
            } else if (role == 4 && codesList.length >= 4) {
                codeSet.add(codesList[3]);
            }
        }

        return new ArrayList<>(codeSet);
    }

    // ======================== 必要的辅助方法（支撑核心方法运行） ========================

    /**
     * 获取区域前缀
     */
    private DataScope getAllDistrictPrefix() {
        int minLevel = SecurityPlusUtils.getMinLevel();
        String area = SecurityPlusUtils.getArea();
        DataScope dataScope = new DataScope();
        dataScope.setUserId(SecurityPlusUtils.getCurrentUserId());
        dataScope.setMinLevel(minLevel);

        if (StringUtils.isNotBlank(area) && minLevel != -1) {
            String[] areaList = area.split(",");
            if (minLevel == 1 || minLevel == 2) {
                dataScope.setArea("460000");
            } else if (minLevel == 3 && areaList.length >= 2) {
                dataScope.setArea(areaList[0] + "," + areaList[1]);
            } else if (minLevel == 4 && areaList.length >= 3) {
                if (area.contains("460100") || area.contains("460200") || area.contains("460300")) {
                    dataScope.setArea(areaList[0] + "," + areaList[1] + "," + areaList[2]);
                }
            }
        }
        return dataScope;
    }

    /**
     * 获取区域后缀
     */
    private List<String> getAllDistrictAfter(DataScope dataScope) {
        if (dataScope == null || StringUtils.isEmpty(dataScope.getArea())) {
            return Collections.emptyList();
        }

        int userRole = dataScope.getMinLevel();
        if (userRole == -1) {
            throw new RuntimeException("用户角色信息错误");
        }

        List<CommCity> cityList = commCityMapper.selectDistinctLevelCodeByArea(dataScope.getArea());
        if (cityList.isEmpty()) {
            return Collections.emptyList();
        }

        Set<String> codeSet = new HashSet<>();
        for (CommCity city : cityList) {
            String[] codesList = city.getLevelCode().split(",");
            if ((userRole == 1 || userRole == 2) && codesList.length >= 2) {
                if ((codesList[1].equals("460100") || codesList[1].equals("460200") || codesList[1].equals("460300")) && codesList.length >= 3) {
                    codeSet.add(codesList[1] + "," + codesList[2]);
                } else if (!Arrays.asList("460100", "460200", "460300").contains(codesList[1])) {
                    codeSet.add(codesList[1]);
                }
            } else if (userRole == 3 && codesList.length >= 2) {
                if (Arrays.asList("460100", "460200", "460300").contains(codesList[1]) && codesList.length >= 3) {
                    codeSet.add(codesList[2]);
                } else {
                    codeSet.add(codesList[1]);
                }
            } else if (userRole == 4 && codesList.length >= 3) {
                codeSet.add(codesList[2]);
            }
        }
        return new ArrayList<>(codeSet);
    }

    /**
     * 计算Double类型合计
     */
    private SelectDoubleSum calculateDoubleTotalSum(List<IncomeExpenditure> entityList) {
        SelectDoubleSum sum = new SelectDoubleSum();
        if (entityList.isEmpty()) {
            return sum;
        }

        sum.setCityAllocatedSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getCityAllocated)));
        sum.setDistrictAllocatedSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getDistrictAllocated)));
        sum.setOtherFundsSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getOtherFunds)));
        sum.setTotalFundsSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getTotalFunds)));
        sum.setPurchaseMaintainSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getPurchaseMaintain)));
        sum.setPurchaseEquipmentSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getPurchaseEquipment)));
        sum.setDiseasePreventionSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getDiseasePrevention)));
        sum.setExpertTrainingSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getExpertTraining)));
        sum.setThirdPartyServiceSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getThirdPartyService)));
        sum.setOtherPaymentSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getOtherPayment)));
        sum.setTotalPaymentSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getTotalPayment)));
        sum.setCityRecoveredSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getCityRecovered)));
        sum.setDistrictRecoveredSum(IECommUtil.longToDouble(sumByFunction(entityList, IncomeExpenditure::getDistrictRecovered)));

        return sum;
    }

    /**
     * 通用求和工具
     */
    private <T> Long sumByFunction(List<T> entityList, java.util.function.Function<T, Long> field) {
        if (entityList.isEmpty()) {
            return 0L;
        }
        return entityList.stream()
                .map(field)
                .mapToLong(value -> value == null ? 0L : value)
                .sum();
    }

    /**
     * Entity转UpdateDoubleVO
     */
    private UpdateDoubleVO iEToVO(IncomeExpenditure entity) {
        UpdateDoubleVO vo = new UpdateDoubleVO();
        if (entity == null) {
            return vo;
        }

        // 基础字段
        vo.setId(entity.getId())
                .setCode(entity.getCode())
                .setDistrict(entity.getDistrict())
                .setYear(entity.getYear());

        // 金额字段转换（Long→Double）
        vo.setCityAllocated(IECommUtil.longToDouble(entity.getCityAllocated()))
                .setDistrictAllocated(IECommUtil.longToDouble(entity.getDistrictAllocated()))
                .setOtherFunds(IECommUtil.longToDouble(entity.getOtherFunds()))
                .setTotalFunds(IECommUtil.longToDouble(entity.getTotalFunds()))
                .setPurchaseMaintain(IECommUtil.longToDouble(entity.getPurchaseMaintain()))
                .setPurchaseEquipment(IECommUtil.longToDouble(entity.getPurchaseEquipment()))
                .setDiseasePrevention(IECommUtil.longToDouble(entity.getDiseasePrevention()))
                .setExpertTraining(IECommUtil.longToDouble(entity.getExpertTraining()))
                .setThirdPartyService(IECommUtil.longToDouble(entity.getThirdPartyService()))
                .setOtherPayment(IECommUtil.longToDouble(entity.getOtherPayment()))
                .setTotalPayment(IECommUtil.longToDouble(entity.getTotalPayment()))
                .setCityRecovered(IECommUtil.longToDouble(entity.getCityRecovered()))
                .setDistrictRecovered(IECommUtil.longToDouble(entity.getDistrictRecovered()));

        return vo;
    }

    /**
     * 处理修改数据
     */
    private List<IncomeExpenditure> handleUpdateData(List<UpdateDoubleDTO> updateDTOList) {
        if (updateDTOList.isEmpty()) {
            return Collections.emptyList();
        }

        // 提取ID并查询原始数据
        List<String> updateIds = updateDTOList.stream()
                .map(UpdateDoubleDTO::getId)
                .collect(Collectors.toList());
        List<IncomeExpenditure> originalEntities = this.list(new LambdaQueryWrapper<IncomeExpenditure>()
                .in(IncomeExpenditure::getId, updateIds)
                .eq(IncomeExpenditure::getDeleted, 0));

        // 校验数据存在性
        if (originalEntities.size() != updateIds.size()) {
            List<String> existIds = originalEntities.stream()
                    .map(IncomeExpenditure::getId)
                    .collect(Collectors.toList());
            List<String> invalidIds = updateIds.stream()
                    .filter(id -> !existIds.contains(id))
                    .collect(Collectors.toList());
            throw new RuntimeException("ID为" + String.join(",", invalidIds) + "的数据不存在或已删除");
        }

        // 构建原始数据映射
        Map<String, IncomeExpenditure> originalMap = originalEntities.stream()
                .collect(Collectors.toMap(IncomeExpenditure::getId, java.util.function.Function.identity()));

        // 构建修改实体
        return updateDTOList.stream()
                .map(dto -> {
                    IncomeExpenditure original = originalMap.get(dto.getId());
                    // 校验修改合法性
                    if (StringUtils.isNotBlank(dto.getYear()) && !Integer.valueOf(dto.getYear()).equals(original.getYear())) {
                        throw new RuntimeException("ID为" + dto.getId() + "的数据禁止修改年份");
                    }
                    if (StringUtils.isNotBlank(dto.getCode()) && !dto.getCode().equals(original.getCode())) {
                        throw new RuntimeException("ID为" + dto.getId() + "的数据code不匹配");
                    }

                    // 建造者模式构建实体
                    return IncomeExpenditureBuilder.anIncomeExpenditure()
                            .fromOriginal(original)
                            .withMoneyFields(moneyToDB(dto))
                            .withUpdateInfo(SecurityPlusUtils.getCurrentUsername())
                            .build();
                })
                .collect(Collectors.toList());
    }

    /**
     * 处理新增数据
     */
    private List<IncomeExpenditure> handleInsertData(List<UpdateDoubleDTO> insertDTOList) {
        if (insertDTOList.isEmpty()) {
            return Collections.emptyList();
        }

        int currentYear = java.time.LocalDate.now().getYear();
        return insertDTOList.stream()
                .map(dto -> {
                    // 校验年份
                    int inputYear = Integer.parseInt(dto.getYear());
                    if (inputYear > currentYear) {
                        throw new RuntimeException("新增失败：年份" + inputYear + "不能大于当前年" + currentYear);
                    }

                    // 查询城市信息
                    CommCity commCity = commCityMapper.selectOne(new LambdaQueryWrapper<CommCity>()
                            .eq(CommCity::getCode, dto.getCode())
                            .eq(CommCity::getDeleted, 0));
                    if (commCity == null) {
                        throw new RuntimeException("新增失败：未找到code=" + dto.getCode() + "的城市信息");
                    }

                    // 处理区域名称
                    String district = dto.getDistrict();
                    if (district.contains("-")) {
                        district = commCity.getName();
                    }
                    if (commCity.getLevelCode().contains("460100") && !district.startsWith("海口市-")) {
                        district = "海口市-" + district;
                    } else if (commCity.getLevelCode().contains("460200") && !district.startsWith("三亚市-")) {
                        district = "三亚市-" + district;
                    } else if (commCity.getLevelCode().contains("460300") && !district.startsWith("三沙市-")) {
                        district = "三沙市-" + district;
                    }

                    // 建造者模式构建实体
                    return IncomeExpenditureBuilder.anIncomeExpenditure()
                            .withId(IDWork.getSequenceId2String())
                            .withCode(commCity.getCode())
                            .withDistrict(district)
                            .withYear(inputYear)
                            .withLevelCode(commCity.getLevelCode())
                            .withMergerName(commCity.getMergerName())
                            .withParentCode(commCity.getParentCode())
                            .withMoneyFields(moneyToDB(dto))
                            .withCreateInfo(SecurityPlusUtils.getCurrentUsername())
                            .build();
                })
                .collect(Collectors.toList());
    }

    /**
     * DTO金额字段转数据库Long类型
     */
    private IncomeExpenditure moneyToDB(UpdateDoubleDTO dto) {
        IncomeExpenditure entity = new IncomeExpenditure();
        if (dto.getCityAllocated() != null) {
            entity.setCityAllocated(IECommUtil.transferToLong(dto.getCityAllocated()));
        }
        if (dto.getDistrictAllocated() != null) {
            entity.setDistrictAllocated(IECommUtil.transferToLong(dto.getDistrictAllocated()));
        }
        if (dto.getOtherFunds() != null) {
            entity.setOtherFunds(IECommUtil.transferToLong(dto.getOtherFunds()));
        }
        if (dto.getPurchaseMaintain() != null) {
            entity.setPurchaseMaintain(IECommUtil.transferToLong(dto.getPurchaseMaintain()));
        }
        if (dto.getPurchaseEquipment() != null) {
            entity.setPurchaseEquipment(IECommUtil.transferToLong(dto.getPurchaseEquipment()));
        }
        if (dto.getDiseasePrevention() != null) {
            entity.setDiseasePrevention(IECommUtil.transferToLong(dto.getDiseasePrevention()));
        }
        if (dto.getExpertTraining() != null) {
            entity.setExpertTraining(IECommUtil.transferToLong(dto.getExpertTraining()));
        }
        if (dto.getThirdPartyService() != null) {
            entity.setThirdPartyService(IECommUtil.transferToLong(dto.getThirdPartyService()));
        }
        if (dto.getOtherPayment() != null) {
            entity.setOtherPayment(IECommUtil.transferToLong(dto.getOtherPayment()));
        }
        if (dto.getCityRecovered() != null) {
            entity.setCityRecovered(IECommUtil.transferToLong(dto.getCityRecovered()));
        }
        if (dto.getDistrictRecovered() != null) {
            entity.setDistrictRecovered(IECommUtil.transferToLong(dto.getDistrictRecovered()));
        }

        // 自动计算合计
        entity.setTotalFunds(calcFundsSourceTotal(entity));
        entity.setTotalPayment(calcPaymentTotal(entity));

        return entity;
    }

    /**
     * 计算经费来源合计
     */
    private Long calcFundsSourceTotal(IncomeExpenditure entity) {
        long city = entity.getCityAllocated() == null ? 0 : entity.getCityAllocated();
        long district = entity.getDistrictAllocated() == null ? 0 : entity.getDistrictAllocated();
        long other = entity.getOtherFunds() == null ? 0 : entity.getOtherFunds();
        return city + district + other;
    }

    /**
     * 计算已支付合计
     */
    private Long calcPaymentTotal(IncomeExpenditure entity) {
        long facility = entity.getPurchaseMaintain() == null ? 0 : entity.getPurchaseMaintain();
        long equipment = entity.getPurchaseEquipment() == null ? 0 : entity.getPurchaseEquipment();
        long publicity = entity.getDiseasePrevention() == null ? 0 : entity.getDiseasePrevention();
        long expert = entity.getExpertTraining() == null ? 0 : entity.getExpertTraining();
        long thirdParty = entity.getThirdPartyService() == null ? 0 : entity.getThirdPartyService();
        long other = entity.getOtherPayment() == null ? 0 : entity.getOtherPayment();
        return facility + equipment + publicity + expert + thirdParty + other;
    }

    /**
     * 构建返回结果
     */
    private List<UpdateDoubleVO> buildResult(List<IncomeExpenditure> updateEntities, List<IncomeExpenditure> insertEntities) {
        List<String> allIds = Stream.concat(
                updateEntities.stream().map(IncomeExpenditure::getId),
                insertEntities.stream().map(IncomeExpenditure::getId)
        ).collect(Collectors.toList());

        List<IncomeExpenditure> resultEntities = this.listByIds(allIds);
        return resultEntities.stream()
                .map(this::iEToVO)
                .collect(Collectors.toList());
    }

    // ======================== 未使用的方法（按需求删除，此处保留空实现） ========================
    @Override
    public List<IncomeExpenditureDetailVO> batchUpdateIncomeExpenditureData(List<UpdateIncomeExpenditureDTO> updateList) {
        throw new UnsupportedOperationException("该方法暂未实现");
    }

    @Override
    public List<IncomeExpenditureDetailVO> updateOrInsertIE(List<UpdateOrInsertIEDTO> dataList) {
        return Collections.emptyList();
    }

    @Override
    public List<IncomeExpenditure> getAllData() {
        return this.list();
    }
}